package com.dianwang.utils;

import com.huaban.analysis.jieba.JiebaSegmenter;
import com.huaban.analysis.jieba.SegToken;
import com.huaban.analysis.jieba.WordDictionary;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * 增强逻辑：
 * 1. 如果 inputText 包含 defectDescription 中的一些词，则提高分数
 * 2. 实际用上 SynonymDictionary 中的同义词，提升匹配效果
 */
public class DefectMatcherAdvanced {
    private DefectLibrary defectLibrary;
    // 同义词词典：在构造函数中注入
    private SynonymDictionary synonymDictionary;

    // 常见的缺陷关键词，可用于加分
    private List<String> defectAllWords = Arrays.asList(
            "漏油", "渗油", "发热", "硅胶变色", "油封油过少",
            "油封油过多", "密封不良", "故障", "加热器损坏",
            "指示不正确", "空开合不上", "破损", "锈蚀",
            "受潮", "感温线故障", "接点发信", "拒动",
            "内部渗油", "油位过高", "油位过低", "油位模糊",
            "面板无显示", "装置报警", "控制故障",
            "计数器故障", "发热", "漏油"
    );

    public static JiebaSegmenter segmenter = new JiebaSegmenter();
    // 静态代码块：加载用户词典
    static {
        // 定义用户词典的文件路径
        Path userDictPath = Paths.get("C:\\Users\\wrt\\Desktop\\code\\dianwang\\dianwang\\src\\main\\resources\\userdict.txt");
        if (Files.exists(userDictPath)) {
            // 使用 WordDictionary 加载用户词典
            WordDictionary.getInstance().loadUserDict(userDictPath);
            System.out.println("[INFO] 用户词典加载成功!");
        } else {
            System.out.println("[WARN] userdict.txt 未找到!");
        }
    }
    /**
     * 新增: 支持从外部注入 SynonymDictionary
     */
    public DefectMatcherAdvanced(DefectLibrary defectLibrary, SynonymDictionary synonymDictionary) {
        this.defectLibrary = defectLibrary;
        this.synonymDictionary = synonymDictionary;
    }

    /**
     * 原有构造函数（如果需要保留）
     * 不用同义词词典时，可调用此构造
     */
    public DefectMatcherAdvanced(DefectLibrary defectLibrary) {
        this(defectLibrary, null);
    }

    /**
     * 获取最匹配的 Top-K 缺陷（基于关键词匹配 + 同义词扩展）
     *
     * @param inputText 缺陷内容文本
     * @param k         Top-K 数量
     * @return List<ScoredDefect> 最匹配的 Top-K 缺陷
     */
    public List<ScoredDefect> getTopKDefectsWithMatchedTokens(String inputText, int k) {
        if (inputText == null || inputText.trim().isEmpty()) {
            return Collections.emptyList();
        }

        // 对输入文本进行分词，并进行同义词扩展
        Set<String> inputWords = textToWordSet(inputText);
        expandWithSynonyms(inputWords);

        // 计算每条缺陷的相似度
        List<ScoredDefect> scoredList = new ArrayList<>();
        for (DefectLibrary.Defect d : defectLibrary.getDefects()) {
            // 如果设备类型不匹配，跳过
            if (!inputText.contains(d.getDevice())) {
                continue;
            }

            // 组合缺陷文本：device + deviceType + part + defectDescription + partType + position + defectClassification
            String combinedText = (d.getDevice() == null ? "" : d.getDevice()) + " "
                    + (d.getDeviceType() == null ? "" : d.getDeviceType()) + " "
                    + (d.getPart() == null ? "" : d.getPart()) + " "
                    + (d.getDefectDescription() == null ? "" : d.getDefectDescription()) + " "
                    + (d.getPartType() == null ? "" : d.getPartType()) + " "
                    + (d.getPosition() == null ? "" : d.getPosition()) + " "
                    + (d.getDefectClassification() == null ? "" : d.getDefectClassification());

            // 对缺陷文本分词，并进行同义词扩展
            Set<String> defectWords = textToWordSet(combinedText);
            expandWithSynonyms(defectWords);

            // 统计得分
            List<String> matchedTokens = new ArrayList<>();
            int intersectionCount = 0;

            // 遍历缺陷文本的每个分词，检查是否在输入文本中出现
            for (String w : defectWords) {
                // 跳过纯数字
                if (w.matches("\\d+")) {
                    continue;
                }
                if (w.length() < 2) {
                    continue;
                }
                // 如果在输入文本的词集合中出现
                if (inputWords.contains(w)) {
                    // 出现一次就 +1
                    intersectionCount += countOccurrences(inputText, w);
                    // 如果该词是常见缺陷关键词，再额外加分
                    if (defectAllWords.contains(w)) {
                        intersectionCount += 5; // 原逻辑是 +1，这里示例加 5
                    }
                    matchedTokens.add(w);
                }
            }

            // 额外加分逻辑
            if (d.getPosition() != null && !d.getPosition().isEmpty() && inputWords.contains(d.getPosition())) {
                intersectionCount += 10;
            }
            if (d.getDefectDescription() != null && inputWords.contains(d.getDefectDescription())) {
                intersectionCount += 10;
            }

            // 根据描述中的词进行额外加分
            intersectionCount += calculateDescriptionScore(inputText, d.getDefectDescription());

            double score = intersectionCount;
            scoredList.add(new ScoredDefect(d, score, matchedTokens));
        }

        // 按分数降序排序
        scoredList.sort((a, b) -> Double.compare(b.score, a.score));

        // 取前 K
        List<ScoredDefect> topk = new ArrayList<>();
        for (int i = 0; i < Math.min(k, scoredList.size()); i++) {
            topk.add(scoredList.get(i));
        }
        return topk;
    }

    /**
     * 将文本转换为词集合（使用结巴分词）
     */
    private static Set<String> textToWordSet(String text) {
        if (text == null) return Collections.emptySet();

        List<SegToken> tokens = segmenter.process(text, JiebaSegmenter.SegMode.SEARCH);
        Set<String> result = new HashSet<>();
        for (SegToken token : tokens) {
            // 忽略单个字符的词
            if (token.word.length() < 2) continue;
            result.add(token.word);
        }
        return result;
    }

    /**
     * 对给定的分词集合进行同义词扩展
     *  - 如果 synonymDictionary 不为 null，则对每个词获取同义词并加入
     */
    private void expandWithSynonyms(Set<String> wordSet) {
        if (synonymDictionary == null) {
            return; // 如果没有同义词词典，直接返回
        }
        // 先拷贝原始单词，避免在遍历时修改 Set
        List<String> originalWords = new ArrayList<>(wordSet);
        for (String w : originalWords) {
            List<String> synonyms = synonymDictionary.getSynonyms(w);
            if (synonyms != null && !synonyms.isEmpty()) {
                wordSet.addAll(synonyms);
            }
        }
    }

    /**
     * 如果 inputText 包含缺陷的 description 中的一些词，则提高分数
     * 示例逻辑：每个分词匹配到就加 1 分
     */
    private int calculateDescriptionScore(String inputText, String defectDescription) {
        if (inputText == null || inputText.isEmpty() || defectDescription == null || defectDescription.isEmpty()) {
            return 0;
        }
        Set<String> descWords = textToWordSet(defectDescription);
        // 如果需要，也可对 descWords 再做同义词扩展

        int bonusScore = 0;
        for (String w : descWords) {
            if (inputText.contains(w)) {
                bonusScore++;
            }
        }
        return bonusScore;
    }

    /**
     * 计算字符串中目标字符串出现的次数
     */
    public int countOccurrences(String mainString, String targetString) {
        if (mainString == null || targetString == null || targetString.isEmpty()) {
            return 0;
        }
        int count = 0;
        int index = 0;
        while ((index = mainString.indexOf(targetString, index)) != -1) {
            count++;
            index += targetString.length();
        }
        return count;
    }

    /**
     * 封装 缺陷 + 分数 + 匹配词
     */
    public static class ScoredDefect {
        private DefectLibrary.Defect defect;
        private double score;
        private List<String> matchedTokens; // 匹配到的关键词

        public ScoredDefect(DefectLibrary.Defect defect, double score, List<String> matchedTokens) {
            this.defect = defect;
            this.score = score;
            this.matchedTokens = matchedTokens;
        }

        public DefectLibrary.Defect getDefect() {
            return defect;
        }

        public double getScore() {
            return score;
        }

        public List<String> getMatchedTokens() {
            return matchedTokens;
        }
    }

    // 测试分词功能
    public static void main(String[] args) {
        String sentence = "500kV济南变电站#2主变本体C相1号9号冷却器漏油压力释放装置\n";
        Set<String> words = textToWordSet(sentence);
        System.out.println("分词结果：" + words);
    }
}
